var PUZZCODE = [];
PUZZCODE['num'] = 0;
PUZZCODE['html'] = [];


function parseurl(str, mode, parsecode) {
	str= str.replace(/\s*\[code\]([\s\S]+?)\[\/code\]\s*/ig, function($1, $2) {return codetag($2);});
	str = str.replace(/([^>=\]"'\/@]|^)((((https?|ftp|gopher|news|telnet|rtsp|mms|callto|bctp|ed2k|thunder|qqdl|synacast):\/\/))([\w\-]+\.)*[:\.@\-\w\u4e00-\u9fa5]+\.([\.a-zA-Z0-9]+|\u4E2D\u56FD|\u7F51\u7EDC|\u516C\u53F8)((\?|\/|:)+[\w\.\/=\?%\-&;~`@':+!#]*)*)/ig, mode == 'html' ? '$1<a href="$2" target="_blank">$2</a>' : '$1[url]$2[/url]');
	str = str.replace(/([^\w>=\]"'\/@]|^)((www\.)([\w\-]+\.)*[:\.@\-\w\u4e00-\u9fa5]+\.([\.a-zA-Z0-9]+|\u4E2D\u56FD|\u7F51\u7EDC|\u516C\u53F8)((\?|\/|:)+[\w\.\/=\?%\-&;~`@':+!#]*)*)/ig, mode == 'html' ? '$1<a href="$2" target="_blank">$2</a>' : '$1[url]$2[/url]');
	str = str.replace(/([^\w->=\]:"'\.\/]|^)(([\-\.\w]+@[\.\-\w]+(\.\w+)+))/ig, mode == 'html' ? '$1<a href="mailto:$2">$2</a>' : '$1[email]$2[/email]');
	if(parsecode) {
		for(var i = 0; i <= PUZZCODE['num']; i++) {
			str = str.replace("[\tPUZZ_CODE_" + i + "\t]", PUZZCODE['html'][i]);
		}
	}
	return str;
}

	function parseurl(str, mode, parsecode) {
		str = str.replace(/([^>=\]"'\/@]|^)((((https?|ftp|gopher|news|telnet|rtsp|mms|callto|bctp|ed2k|thunder|qqdl|synacast):\/\/))([\w\-]+\.)*[:\.@\-\w\u4e00-\u9fa5]+\.([\.a-zA-Z0-9]+|\u4E2D\u56FD|\u7F51\u7EDC|\u516C\u53F8)((\?|\/|:)+[\w\.\/=\?%\-&;~`@':+!#]*)*)/ig, mode == 'html' ? '$1<a href="$2" target="_blank">$2</a>' : '$1[url]$2[/url]');
		str = str.replace(/([^\w>=\]"'\/@]|^)((www\.)([\w\-]+\.)*[:\.@\-\w\u4e00-\u9fa5]+\.([\.a-zA-Z0-9]+|\u4E2D\u56FD|\u7F51\u7EDC|\u516C\u53F8)((\?|\/|:)+[\w\.\/=\?%\-&;~`@':+!#]*)*)/ig, mode == 'html' ? '$1<a href="$2" target="_blank">$2</a>' : '$1[url]$2[/url]');
		str = str.replace(/([^\w->=\]:"'\.\/]|^)(([\-\.\w]+@[\.\-\w]+(\.\w+)+))/ig, mode == 'html' ? '$1<a href="mailto:$2">$2</a>' : '$1[email]$2[/email]');
		return str;
	}
	function addslashes(str) {
		return preg_replace(['\\\\', '\\\'', '\\\/', '\\\(', '\\\)', '\\\[', '\\\]', '\\\{', '\\\}', '\\\^', '\\\$', '\\\?', '\\\.', '\\\*', '\\\+', '\\\|'], ['\\\\', '\\\'', '\\/', '\\(', '\\)', '\\[', '\\]', '\\{', '\\}', '\\^', '\\$', '\\?', '\\.', '\\*', '\\+', '\\|'], str);
	}
	function parsecode(text) {
		PUZZCODE['num']++;
		PUZZCODE['html'][PUZZCODE['num']] = '<div class="blockcode"><blockquote>' + htmlspecialchars(text) + '</blockquote></div>';
		return "[\tPUZZ_CODE_" + PUZZCODE['num'] + "\t]";
	}
	function bbcode2html(str,editorid) {
		if (str == '') {
			return '';
		}

		if (typeof (parsetype) == 'undefined') {
			parsetype = 0;
		}
		str = str.replace(/\[code\]([\s\S]+?)\[\/code\]/ig, function($1, $2) {return parsecode($2);});
		str = str.replace(/([^>=\]"'\/]|^)((((https?|ftp):\/\/)|www\.)([\w\-]+\.)*[\w\-\u4e00-\u9fa5]+\.([\.a-zA-Z0-9]+|\u4E2D\u56FD|\u7F51\u7EDC|\u516C\u53F8)((\?|\/|:)+[\w\.\/=\?%\-&~`@':+!]*)+\.(jpg|gif|png|bmp))/ig, '$1[img]$2[/img]');
		str = str.replace(/</g, '&lt;');
		str = str.replace(/>/g, '&gt;');
		str = parseurl(str, 'html', false);
		
		
		str = clearcode(str);
		str = str.replace(/\[url\]\s*((https?|ftp|gopher|news|telnet|rtsp|mms|callto|bctp|thunder|qqdl|synacast){1}:\/\/|www\.)([^\[\"']+?)\s*\[\/url\]/ig, function($1, $2, $3, $4) { return cuturl($2 + $4);});
		str = str.replace(/\[url=((https?|ftp|gopher|news|telnet|rtsp|mms|callto|bctp|thunder|qqdl|synacast){1}:\/\/|www\.|mailto:)?([^\r\n\[\"']+?)\]([\s\S]+?)\[\/url\]/ig, '<a href="$1$3" target="_blank">$4</a>');
		str = str.replace(/\[email\](.*?)\[\/email\]/ig, '<a href="mailto:$1">$1</a>');
		str = str.replace(/\[email=(.[^\[]*)\](.*?)\[\/email\]/ig, '<a href="mailto:$1" target="_blank">$2</a>');
		str = str.replace(/\[color=([^\[\<]+?)\]/ig, '<font color="$1">');
		str = str.replace(/\[backcolor=([^\[\<]+?)\]/ig, '<font style="background-color:$1">');
		str = str.replace(/\[size=(\d+?)\]/ig, '<font size="$1">');
		str = str.replace(/\[size=(\d+(\.\d+)?(px|pt)+?)\]/ig, '<font style="font-size: $1">');
		str = str.replace(/\[font=([^\[\<]+?)\]/ig, '<font face="$1">');
		str = str.replace(/\[align=([^\[\<]+?)\]/ig, '<div align="$1">');
		str = str.replace(/\[p=(\d{1,2}|null), (\d{1,2}|null), (left|center|right)\]/ig, '<p style="line-height: $1px; text-indent: $2em; text-align: $3;">');
		str = str.replace(/\[float=left\]/ig, '<br style="clear: both"><span style="float: left; margin-right: 5px;">');
		str = str.replace(/\[float=right\]/ig, '<br style="clear: both"><span style="float: right; margin-left: 5px;">');
		if (parsetype != 1) {
			str = str.replace(/\[quote]([\s\S]*?)\[\/quote\]\s?\s?/ig, '<div class="quote"><blockquote>$1</blockquote></div>\n');
		}

		re = /\[table(?:=(\d{1,4}%?)(?:,([\(\)%,#\w ]+))?)?\]\s*([\s\S]+?)\s*\[\/table\]/ig;
		for (i = 0; i < 4; i++) {
			str = str.replace(re, function($1, $2, $3, $4) {
				return parsetable($2, $3, $4);
			});
		}

		str = preg_replace([ '\\\[\\\/color\\\]', '\\\[\\\/backcolor\\\]',
				'\\\[\\\/size\\\]', '\\\[\\\/font\\\]', '\\\[\\\/align\\\]',
				'\\\[\\\/p\\\]', '\\\[b\\\]', '\\\[\\\/b\\\]', '\\\[i\\\]',
				'\\\[\\\/i\\\]', '\\\[u\\\]', '\\\[\\\/u\\\]', '\\\[s\\\]',
				'\\\[\\\/s\\\]', '\\\[hr\\\]', '\\\[list\\\]',
				'\\\[list=1\\\]', '\\\[list=a\\\]', '\\\[list=A\\\]',
				'\\s?\\\[\\\*\\\]', '\\\[\\\/list\\\]', '\\\[indent\\\]',
				'\\\[\\\/indent\\\]', '\\\[\\\/float\\\]' ], [ '</font>',
				'</font>', '</font>', '</font>', '</div>', '</p>', '<b>',
				'</b>', '<i>', '</i>', '<u>', '</u>', '<strike>', '</strike>',
				'<hr class="l" />', '<ul>', '<ul type=1 class="litype_1">',
				'<ul type=a class="litype_2">', '<ul type=A class="litype_3">',
				'<li>', '</ul>', '<blockquote>', '</blockquote>', '</span>' ],
				str, 'g');

		str = str.replace(/\[img\]\s*([^\[\<\r\n]+?)\s*\[\/img\]/ig, '<img src="$1" border="0" alt="" style="max-width:400px" />');
		str = str.replace(/\[attachimg\](\d+)\[\/attachimg\]/ig, function ($1, $2) {
			if(!PZEM(editorid+'_' + $2)) {
				return '';
			}
			return '<img src="' + PZEM(editorid+'_' + $2).src + '" border="0" aid="attachimg_' + $2 + '" style="max-width:400px" alt="" />';
		});

		str = str.replace(/\[remoteimg\]\s*([^\[\<\r\n]+?)\s*\[\/remoteimg\]/ig, '<img src="$1" border="0" alt="" remoteimg="$1" style="max-width:400px" />');
		
		str = str.replace(/\[img=(\d{1,4})[x|\,](\d{1,4})\]\s*([^\[\<\r\n]+?)\s*\[\/img\]/ig, function ($1, $2, $3, $4) {return '<img' + ($2 > 0 ? ' width="' + $2 + '"' : '') + ($3 > 0 ? ' iheight="' + $3 + '"' : '') + ' src="' + $4 + '" border="0" alt="" />'});
		
		for(var i = 0; i <= PUZZCODE['num']; i++) {
			str = str.replace("[\tPUZZ_CODE_" + i + "\t]", PUZZCODE['html'][i]);
		}
		str = str.replace(/(^|>)([^<]+)(?=<|$)/ig, function($1, $2, $3) {
			return $2 + preg_replace(['\t', '   ', '  ', '(\r\n|\n|\r)'], ['&nbsp; &nbsp; &nbsp; &nbsp; ', '&nbsp; &nbsp;', '&nbsp;&nbsp;', '<br />'], $3);
		});
		return str;
	}

	function clearcode(str) {
		str= str.replace(/\[url\]\[\/url\]/ig, '', str);
		str= str.replace(/\[url=((https?|ftp|gopher|news|telnet|rtsp|mms|callto|bctp|thunder|qqdl|synacast){1}:\/\/|www\.|mailto:)?([^\s\[\"']+?)\]\[\/url\]/ig, '', str);
		str= str.replace(/\[email\]\[\/email\]/ig, '', str);
		str= str.replace(/\[email=(.[^\[]*)\]\[\/email\]/ig, '', str);
		str= str.replace(/\[color=([^\[\<]+?)\]\[\/color\]/ig, '', str);
		str= str.replace(/\[size=(\d+?)\]\[\/size\]/ig, '', str);
		str= str.replace(/\[size=(\d+(\.\d+)?(px|pt)+?)\]\[\/size\]/ig, '', str);
		str= str.replace(/\[font=([^\[\<]+?)\]\[\/font\]/ig, '', str);
		str= str.replace(/\[align=([^\[\<]+?)\]\[\/align\]/ig, '', str);
		str= str.replace(/\[p=(\d{1,2}), (\d{1,2}), (left|center|right)\]\[\/p\]/ig, '', str);
		str= str.replace(/\[float=([^\[\<]+?)\]\[\/float\]/ig, '', str);
		str= str.replace(/\[quote\]\[\/quote\]/ig, '', str);
		str= str.replace(/\[code\]\[\/code\]/ig, '', str);
		str= str.replace(/\[table\]\[\/table\]/ig, '', str);
		str= str.replace(/\[free\]\[\/free\]/ig, '', str);
		str= str.replace(/\[b\]\[\/b]/ig, '', str);
		str= str.replace(/\[u\]\[\/u]/ig, '', str);
		str= str.replace(/\[i\]\[\/i]/ig, '', str);
		str= str.replace(/\[s\]\[\/s]/ig, '', str);
		return str;
	}

	function cuturl(url) {
		var length = 65;
		var urllink = '<a href="' + (url.toLowerCase().substr(0, 4) == 'www.' ? 'http://' + url : url) + '" target="_blank">';
		if(url.length > length) {
			url = url.substr(0, parseInt(length * 0.5)) + ' ... ' + url.substr(url.length - parseInt(length * 0.3));
		}
		urllink += url + '</a>';
		return urllink;
	}

	function dstag(options, text, tagname) {
		if(trim(text) == '') {
			return '\n';
		}
		var pend = parsestyle(options, '', '');
		var prepend = pend['prepend'];
		var append = pend['append'];
		if(in_array(tagname, ['div', 'p'])) {
			align = getoptionvalue('align', options);
			if(in_array(align, ['left', 'center', 'right'])) {
				prepend = '[align=' + align + ']' + prepend;
				append += '[/align]';
			} else {
				append += '\n';
			}
		}
		return prepend + recursion(tagname, text, 'dstag') + append;
	}
	
	function ptag(options, text, tagname) {
		if(trim(text) == '') {
			return '\n';
		}
		if(trim(options) == '') {
			return text + '\n';
		}

		var lineHeight = null;
		var textIndent = null;
		var align, re, matches;

		re = /line-height\s?:\s?(\d{1,3})px/i;
		matches = re.exec(options);
		if(matches != null) {
			lineHeight = matches[1];
		}

		re = /text-indent\s?:\s?(\d{1,3})em/i;
		matches = re.exec(options);
		if(matches != null) {
			textIndent = matches[1];
		}

		re = /text-align\s?:\s?(left|center|right)/i;
		matches = re.exec(options);
		if(matches != null) {
			align = matches[1];
		} else {
			align = getoptionvalue('align', options);
		}
		align = in_array(align, ['left', 'center', 'right']) ? align : 'left';
		style = getoptionvalue('style', options);
		style = preg_replace(['line-height\\\s?:\\\s?(\\\d{1,3})px', 'text-indent\\\s?:\\\s?(\\\d{1,3})em', 'text-align\\\s?:\\\s?(left|center|right)'], '', style);
		if(lineHeight === null && textIndent === null) {
			return '[align=' + align + ']' + (style ? '<span style="' + style + '">' : '') + text + (style ? '</span>' : '') + '[/align]';
		} else {
			return '[p=' + lineHeight + ', ' + textIndent + ', ' + align + ']' + (style ? '<span style="' + style + '">' : '') + text + (style ? '</span>' : '') + '[/p]';
		}
	}

	function fetchoptionvalue(option, text) {
		if((position = strpos(text, option)) !== false) {
			delimiter = position + option.length;
			if(text.charAt(delimiter) == '"') {
				delimchar = '"';
			} else if(text.charAt(delimiter) == '\'') {
				delimchar = '\'';
			} else {
				delimchar = ' ';
			}
			delimloc = strpos(text, delimchar, delimiter + 1);
			if(delimloc === false) {
				delimloc = text.length;
			} else if(delimchar == '"' || delimchar == '\'') {
				delimiter++;
			}
			return trim(text.substr(delimiter, delimloc - delimiter));
		} else {
			return '';
		}
	}

	function fonttag(fontoptions, text) {
		var prepend = '';
		var append = '';
		var tags = new Array();
		tags = {'font' : 'face=', 'size' : 'size=', 'color' : 'color='};
		for(bbcode in tags) {
			optionvalue = fetchoptionvalue(tags[bbcode], fontoptions);
			if(optionvalue) {
				prepend += '[' + bbcode + '=' + optionvalue + ']';
				append = '[/' + bbcode + ']' + append;
			}
		}

		var pend = parsestyle(fontoptions, prepend, append);
		return pend['prepend'] + recursion('font', text, 'fonttag') + pend['append'];
	}

	function getoptionvalue(option, text) {
		re = new RegExp(option + "(\s+?)?\=(\s+?)?[\"']?(.+?)([\"']|$|>)", "ig");
		var matches = re.exec(text);
		if(matches != null) {
			return trim(matches[3]);
		}
		return '';
	}
	
	function codetag(text) {
		PUZZCODE['num']++;
		text = text.replace(/<br[^\>]*>/ig, '\n');
		PUZZCODE['html'][PUZZCODE['num']] = '[code]' + text + '[/code]';
		return '[\tPUZZ_CODE_' + PUZZCODE['num'] + '\t]';
	}

	function html2bbcode(str) {
		
		str = str.replace(/<div\sclass=["']?blockcode["']?>[\s\S]*?<blockquote>([\s\S]+?)<\/blockquote>[\s\S]*?<\/div>/ig, function($1, $2) {return codetag($2);});

		str = preg_replace(['<style.*?>[\\\s\\\S]*?<\/style>', '<script.*?>[\\\s\\\S]*?<\/script>', '<noscript.*?>[\\\s\\\S]*?<\/noscript>', '<select.*?>[\s\S]*?<\/select>', '<object.*?>[\s\S]*?<\/object>', '<!--[\\\s\\\S]*?-->', ' on[a-zA-Z]{3,16}\\\s?=\\\s?"[\\\s\\\S]*?"'], '', str);

		str= str.replace(/(\r\n|\n|\r)/ig, '');

		str= str.replace(/&((#(32|127|160|173))|shy|nbsp);/ig, ' ');

		str = str.replace(/([^>=\]"'\/]|^)((((https?|ftp):\/\/)|www\.)([\w\-]+\.)*[\w\-\u4e00-\u9fa5]+\.([\.a-zA-Z0-9]+|\u4E2D\u56FD|\u7F51\u7EDC|\u516C\u53F8)((\?|\/|:)+[\w\.\/=\?%\-&~`@':+!]*)+\.(jpg|gif|png|bmp))/ig, '$1[img]$2[/img]');
		
		str = parseurl(str, 'bbcode', false);
		str = str.replace(/<br\s+?style=(["']?)clear: both;?(\1)[^\>]*>/ig, '');
		str = str.replace(/<br[^\>]*>/ig, "\n");

			str = preg_replace([
				'<table[^>]*float:\\\s*(left|right)[^>]*><tbody><tr><td>\\\s*([\\\s\\\S]+?)\\\s*<\/td><\/tr></tbody><\/table>',
				'<table([^>]*(width|background|background-color|backcolor)[^>]*)>',
				'<table[^>]*>',
				'<tr[^>]*(?:background|background-color|backcolor)[:=]\\\s*(["\']?)([\(\)\\\s%,#\\\w]+)(\\1)[^>]*>',
				'<tr[^>]*>',
				'(<t[dh]([^>]*(left|center|right)[^>]*)>)\\\s*([\\\s\\\S]+?)\\\s*(<\/t[dh]>)',
				'<t[dh]([^>]*(width|colspan|rowspan)[^>]*)>',
				'<t[dh][^>]*>',
				'<\/t[dh]>',
				'<\/tr>',
				'<\/table>',
				'<h\\\d[^>]*>',
				'<\/h\\\d>'
			], [
				function($1, $2, $3) {return '[float=' + $2 + ']' + $3 + '[/float]';},
				function($1, $2) {return tabletag($2);},
				'[table]\n',
				function($1, $2, $3) {return '[tr=' + $3 + ']';},
				'[tr]',
				function($1, $2, $3, $4, $5, $6) {return $2 + '[align=' + $4 + ']' + $5 + '[/align]' + $6},
				function($1, $2) {return tdtag($2);},
				'[td]',
				'[/td]',
				'[/tr]\n',
				'[/table]',
				'[b]',
				'[/b]'
			], str);

			str = str.replace(/<h([0-9]+)[^>]*>(.*)<\/h\\1>/ig, "[size=$1]$2[/size]\n\n");
			str = str.replace(/<hr[^>]*>/ig, "[hr]");
			str = str.replace(/<img[^>]+smilieid=(["']?)(\d+)(\1)[^>]*>/ig, function($1, $2, $3) {return smileycode($3);});
			str = str.replace(/<img([^>]*src[^>]*)>/ig, function($1, $2) {return imgtag($2);});
			str = str.replace(/<a\s+?name=(["']?)(.+?)(\1)[\s\S]*?>([\s\S]*?)<\/a>/ig, '$4');

			str = recursion('b', str, 'simpletag', 'b');
			str = recursion('strong', str, 'simpletag', 'b');
			str = recursion('i', str, 'simpletag', 'i');
			str = recursion('em', str, 'simpletag', 'i');
			str = recursion('u', str, 'simpletag', 'u');
			str = recursion('strike', str, 'simpletag', 's');
			str = recursion('a', str, 'atag');
			str = recursion('font', str, 'fonttag');
			str = recursion('blockquote', str, 'simpletag', 'indent');
			str = recursion('ol', str, 'listtag');
			str = recursion('ul', str, 'listtag');
			str = recursion('div', str, 'dstag');
			str = recursion('p', str, 'ptag');
			str = recursion('span', str, 'fonttag');

		str = str.replace(/<[\/\!]*?[^<>]*?>/ig, '');
		for(var i = 0; i <= PUZZCODE['num']; i++) {
			str = str.replace("[\tPUZZ_CODE_" + i + "\t]", PUZZCODE['html'][i]);
		}
		str = clearcode(str);

		return preg_replace(['&nbsp;', '&lt;', '&gt;', '&amp;'], [' ', '<', '>', '&'], str);
	}

	function atag(aoptions, text) {
		if(trim(text) == '') {
			return '';
		}
		var pend = parsestyle(aoptions, '', '');
		href = getoptionvalue('href', aoptions);

		if(href.substr(0, 11) == 'javascript:') {
			return trim(recursion('a', text, 'atag'));
		}

		return pend['prepend'] + '[url=' + href + ']' + trim(recursion('a', text, 'atag')) + '[/url]' + pend['append'];
	}
	
	function tablesimple(s, table, str) {
		if(strpos(str, '[tr=') || strpos(str, '[td=')) {
			return s;
		} else {
			return '[table=' + table + ']\n' + preg_replace(['\\\[tr\\\]', '\\\[\\\/td\\\]\\\s?\\\[td\\\]', '\\\[\\\/tr\\\]\s?', '\\\[td\\\]', '\\\[\\\/td\\\]', '\\\[\\\/td\\\]\\\[\\\/tr\\\]'], ['', '|', '', '', '', '', ''], str) + '[/table]';
		}
	}

	function imgtag(attributes) {
		var width = '';
		var height = '';

		re = /src=(["']?)([\s\S]*?)(\1)/i;
		var matches = re.exec(attributes);
		if(matches != null) {
			var src = matches[2];
		} else {
			return '';
		}

		re = /(max-)?width\s?:\s?(\d{1,4})(px)?/i;
		var matches = re.exec(attributes);
		if(matches != null && !matches[1]) {
			width = matches[2];
		}

		re = /height\s?:\s?(\d{1,4})(px)?/i;
		var matches = re.exec(attributes);
		if(matches != null) {
			height = matches[1];
		}

		if(!width) {
			re = /width=(["']?)(\d+)(\1)/i;
			var matches = re.exec(attributes);
			if(matches != null) {
				width = matches[2];
			}
		}

		if(!height) {
			re = /height=(["']?)(\d+)(\1)/i;
			var matches = re.exec(attributes);
			if(matches != null) {
				height = matches[2];
			}
		}

		re = /aid=(["']?)attachimg_(\d+)(\1)/i;
		var matches = re.exec(attributes);
		if(matches != null) {
			return '[attachimg]' + matches[2] + '[/attachimg]';
		}

		re = /remoteimg=(["']?)([\s\S]*?)(\1)/i;
		var matches = re.exec(attributes);
		if(matches != null) {
			return '[remoteimg]' + src + '[/remoteimg]';
		}

		width = width > 0 ? width : 0;
		height = height > 0 ? height : 0;
		return width > 0 || height > 0 ?
			'[img=' + width + ',' + height + ']' + src + '[/img]' :
			'[img]' + src + '[/img]';
	}

	function listtag(listoptions, text, tagname) {
		text = text.replace(/<li>(([\s\S](?!<\/li))*?)(?=<\/?ol|<\/?ul|<li|\[list|\[\/list)/ig, '<li>$1</li>') + (BROWSER.opera ? '</li>' : '');
		text = recursion('li', text, 'litag');
		var opentag = '[list]';
		var listtype = fetchoptionvalue('type=', listoptions);
		listtype = listtype != '' ? listtype : (tagname == 'ol' ? '1' : '');
		if(in_array(listtype, ['1', 'a', 'A'])) {
			opentag = '[list=' + listtype + ']';
		}
		return text ? opentag + '\n' + recursion(tagname, text, 'listtag') + '[/list]' : '';
	}

	function litag(listoptions, text) {
		return '[*]' + text.replace(/(\s+)$/g, '') + '\n';
	}

	function parsestyle(tagoptions, prepend, append) {
		var searchlist = [
			['align', true, 'text-align:\\s*(left|center|right);?', 1],
			['float', true, 'float:\\s*(left|right);?', 1],
			['color', true, '(^|[;\\s])color:\\s*([^;]+);?', 2],
			['backcolor', true, '(^|[;\\s])background-color:\\s*([^;]+);?', 2],
			['font', true, 'font-family:\\s*([^;]+);?', 1],
			['size', true, 'font-size:\\s*(\\d+(\\.\\d+)?(px|pt|in|cm|mm|pc|em|ex|%|));?', 1],
			['size', true, 'font-size:\\s*(x\\-small|small|medium|large|x\\-large|xx\\-large|\\-webkit\\-xxx\\-large);?', 1, 'size'],
			['b', false, 'font-weight:\\s*(bold);?'],
			['i', false, 'font-style:\\s*(italic);?'],
			['u', false, 'text-decoration:\\s*(underline);?'],
			['s', false, 'text-decoration:\\s*(line-through);?']
		];
		var sizealias = {'x-small':1,'small':2,'medium':3,'large':4,'x-large':5,'xx-large':6,'-webkit-xxx-large':7};
		var style = getoptionvalue('style', tagoptions);
		re = /^(?:\s|)color:\s*rgb\((\d+),\s*(\d+),\s*(\d+)\)(;?)/i;
		style = style.replace(re, function($1, $2, $3, $4, $5) {return("color:#" + parseInt($2).toString(16) + parseInt($3).toString(16) + parseInt($4).toString(16) + $5);});
		var len = searchlist.length;
		for(var i = 0; i < len; i++) {
			searchlist[i][4] = !searchlist[i][4] ? '' : searchlist[i][4];
			re = new RegExp(searchlist[i][2], "ig");
			match = re.exec(style);
			if(match != null) {
				opnvalue = match[searchlist[i][3]];
				if(searchlist[i][4] == 'size') {
					opnvalue = sizealias[opnvalue];
				}
				prepend += '[' + searchlist[i][0] + (searchlist[i][1] == true ? '=' + opnvalue + ']' : ']');
				append = '[/' + searchlist[i][0] + ']' + append;
			}
		}
		return {'prepend' : prepend, 'append' : append};
	}

	function parsetable(width, bgcolor, str) {

		if(isUndefined(width)) {
			var width = '';
		} else {
			try {
				width = width.substr(width.length - 1, width.length) == '%' ? (width.substr(0, width.length - 1) <= 98 ? width : '98%') : (width <= 560 ? width : '98%');
			} catch(e) { width = ''; }
		}
		if(isUndefined(str)) {
			return;
		}

		if(strpos(str, '[/tr]') === false && strpos(str, '[/td]') === false) {
			var rows = str.split('\n');
			var s = '';
			for(i = 0;i < rows.length;i++) {
				s += '<tr><td>' + preg_replace(['\r', '\\\\\\\|', '\\\|', '\\\\n'], ['', '&#124;', '</td><td>', '\n'], rows[i]) + '</td></tr>';
			}
			str = s;
			simple = ' simpletable';
		} else {
			simple = '';
			str = str.replace(/\[tr(?:=([\(\)\s%,#\w]+))?\]\s*\[td(?:=(\d{1,4}%?))?\]/ig, function($1, $2, $3) {
				return '<tr' + ($2 ? ' style="background-color: ' + $2 + '"' : '') + '><td' + ($3 ? ' width="' + $3 + '"' : '') + '>';
			});
			str = str.replace(/\[tr(?:=([\(\)\s%,#\w]+))?\]\s*\[td(?:=(\d{1,2}),(\d{1,2})(?:,(\d{1,4}%?))?)?\]/ig, function($1, $2, $3, $4, $5) {
				return '<tr' + ($2 ? ' style="background-color: ' + $2 + '"' : '') + '><td' + ($3 ? ' colspan="' + $3 + '"' : '') + ($4 ? ' rowspan="' + $4 + '"' : '') + ($5 ? ' width="' + $5 + '"' : '') + '>';
			});
			str = str.replace(/\[\/td\]\s*\[td(?:=(\d{1,4}%?))?\]/ig, function($1, $2) {
				return '</td><td' + ($2 ? ' width="' + $2 + '"' : '') + '>';
			});
			str = str.replace(/\[\/td\]\s*\[td(?:=(\d{1,2}),(\d{1,2})(?:,(\d{1,4}%?))?)?\]/ig, function($1, $2, $3, $4) {
				return '</td><td' + ($2 ? ' colspan="' + $2 + '"' : '') + ($3 ? ' rowspan="' + $3 + '"' : '') + ($4 ? ' width="' + $4 + '"' : '') + '>';
			});
			str = str.replace(/\[\/td\]\s*\[\/tr\]\s*/ig, '</td></tr>');
			str = str.replace(/<td> <\/td>/ig, '<td>&nbsp;</td>');
		}
		return '<table ' + (width == '' ? '' : 'width="' + width + '" ') + 'class="t_table"' + (isUndefined(bgcolor) ? '' : ' style="background-color: ' + bgcolor + '"') + simple +'>' + str + '</table>';
	}

	function preg_quote(str) {
		return (str+'').replace(/([\\\.\+\*\?\[\^\]\$\(\)\{\}\=\!<>\|\:])/g, "\\$1");
	}

	function recursion(tagname, text, dofunction, extraargs) {
		if(extraargs == null) {
			extraargs = '';
		}
		tagname = tagname.toLowerCase();

		var open_tag = '<' + tagname;
		var open_tag_len = open_tag.length;
		var close_tag = '</' + tagname + '>';
		var close_tag_len = close_tag.length;
		var beginsearchpos = 0;

		do {
			var textlower = text.toLowerCase();
			var tagbegin = textlower.indexOf(open_tag, beginsearchpos);
			if(tagbegin == -1) {
				break;
			}

			var strlen = text.length;

			var inquote = '';
			var found = false;
			var tagnameend = false;
			var optionend = 0;
			var t_char = '';

			for(optionend = tagbegin; optionend <= strlen; optionend++) {
				t_char = text.charAt(optionend);
				if((t_char == '"' || t_char == "'") && inquote == '') {
					inquote = t_char;
				} else if((t_char == '"' || t_char == "'") && inquote == t_char) {
					inquote = '';
				} else if(t_char == '>' && !inquote) {
					found = true;
					break;
				} else if((t_char == '=' || t_char == ' ') && !tagnameend) {
					tagnameend = optionend;
				}
			}

			if(!found) {
				break;
			}
			if(!tagnameend) {
				tagnameend = optionend;
			}

			var offset = optionend - (tagbegin + open_tag_len);
			var tagoptions = text.substr(tagbegin + open_tag_len, offset);
			var acttagname = textlower.substr(tagbegin * 1 + 1, tagnameend - tagbegin - 1);

			if(acttagname != tagname) {
				beginsearchpos = optionend;
				continue;
			}

			var tagend = textlower.indexOf(close_tag, optionend);
			if(tagend == -1) {
				break;
			}

			var nestedopenpos = textlower.indexOf(open_tag, optionend);
			while(nestedopenpos != -1 && tagend != -1) {
				if(nestedopenpos > tagend) {
					break;
				}
				tagend = textlower.indexOf(close_tag, tagend + close_tag_len);
				nestedopenpos = textlower.indexOf(open_tag, nestedopenpos + open_tag_len);
			}

			if(tagend == -1) {
				beginsearchpos = optionend;
				continue;
			}

			var localbegin = optionend + 1;
			var localtext = eval(dofunction)(tagoptions, text.substr(localbegin, tagend - localbegin), tagname, extraargs);

			text = text.substring(0, tagbegin) + localtext + text.substring(tagend + close_tag_len);

			beginsearchpos = tagbegin + localtext.length;

		} while(tagbegin != -1);

		return text;
	}

	function simpletag(options, text, tagname, parseto) {
		if(trim(text) == '') {
			return '';
		}
		text = recursion(tagname, text, 'simpletag', parseto);
		return '[' + parseto + ']' + text + '[/' + parseto + ']';
	}

	function smileycode(smileyid) {
		var code = $('#smilie_' + smileyid).attr('alt');
		return code;
	}

	function strpos(haystack, needle, _offset) {
		if(isUndefined(_offset)) {
			_offset = 0;
		}

		var _index = haystack.toLowerCase().indexOf(needle.toLowerCase(), _offset);

		return _index == -1 ? false : _index;
	}

	function tabletag(attributes) {
		var width = '';
		re = /width=(["']?)(\d{1,4}%?)(\1)/i;
		var matches = re.exec(attributes);

		if(matches != null) {
			width = matches[2].substr(matches[2].length - 1, matches[2].length) == '%' ?
				(matches[2].substr(0, matches[2].length - 1) <= 98 ? matches[2] : '98%') :
				(matches[2] <= 560 ? matches[2] : '98%');
		} else {
			re = /width\s?:\s?(\d{1,4})([px|%])/i;
			var matches = re.exec(attributes);
			if(matches != null) {
				width = matches[2] == '%' ? (matches[1] <= 98 ? matches[1] + '%' : '98%') : (matches[1] <= 560 ? matches[1] : '98%');
			}
		}

		var bgcolor = '';
		re = /(?:background|background-color|bgcolor)[:=]\s*(["']?)((rgb\(\d{1,3}%?,\s*\d{1,3}%?,\s*\d{1,3}%?\))|(#[0-9a-fA-F]{3,6})|([a-zA-Z]{1,20}))(\1)/i;
		var matches = re.exec(attributes);
		if(matches != null) {
			bgcolor = matches[2];
			width = width ? width : '98%';
		}
		return bgcolor ? '[table=' + width + ',' + bgcolor + ']\n' : (width ? '[table=' + width + ']\n' : '[table]\n');
	}

	function tdtag(attributes) {

		var colspan = 1;
		var rowspan = 1;
		var width = '';

		re = /colspan=(["']?)(\d{1,2})(\1)/i;
		var matches = re.exec(attributes);
		if(matches != null) {
			colspan = matches[2];
		}

		re = /rowspan=(["']?)(\d{1,2})(\1)/i;
		var matches = re.exec(attributes);
		if(matches != null) {
			rowspan = matches[2];
		}

		re = /width=(["']?)(\d{1,4}%?)(\1)/i;
		var matches = re.exec(attributes);
		if(matches != null) {
			width = matches[2];
		}

		return in_array(width, ['', '0', '100%']) ?
			(colspan == 1 && rowspan == 1 ? '[td]' : '[td=' + colspan + ',' + rowspan + ']') :
			(colspan == 1 && rowspan == 1 ? '[td=' + width + ']' : '[td=' + colspan + ',' + rowspan + ',' + width + ']');
	}
	function PZEM(id) {
		return !id ? null : document.getElementById(id);
	}
	
	function showMenu(v) {
		var ctrlid = isUndefined(v['ctrlid']) ? v : v['ctrlid'];
		var showid = isUndefined(v['showid']) ? ctrlid : v['showid'];
		var menuid = isUndefined(v['menuid']) ? showid + '_menu' : v['menuid'];
		var ctrlObj = PZEM(ctrlid);
		var menuObj = PZEM(menuid);
		if(!menuObj) return;
		var mtype = isUndefined(v['mtype']) ? 'menu' : v['mtype'];
		var evt = isUndefined(v['evt']) ? 'mouseover' : v['evt'];
		var pos = isUndefined(v['pos']) ? '43' : v['pos'];
		var layer = isUndefined(v['layer']) ? 1 : v['layer'];
		var duration = isUndefined(v['duration']) ? 2 : v['duration'];
		var timeout = isUndefined(v['timeout']) ? 250 : v['timeout'];
		var maxh = isUndefined(v['maxh']) ? 600 : v['maxh'];
		var cache = isUndefined(v['cache']) ? 1 : v['cache'];
		var drag = isUndefined(v['drag']) ? '' : v['drag'];
		var dragobj = drag && PZEM(drag) ? PZEM(drag) : menuObj;
		var fade = isUndefined(v['fade']) ? 0 : v['fade'];
		var cover = isUndefined(v['cover']) ? 0 : v['cover'];
		var zindex = isUndefined(v['zindex']) ? JSMENU['zIndex']['menu'] : v['zindex'];
		var ctrlclass = isUndefined(v['ctrlclass']) ? '' : v['ctrlclass'];
		var winhandlekey = isUndefined(v['win']) ? '' : v['win'];
		zindex = cover ? zindex + 500 : zindex;
		if(typeof JSMENU['active'][layer] == 'undefined') {
			JSMENU['active'][layer] = [];
		}

		if(evt == 'click' && in_array(menuid, JSMENU['active'][layer]) && mtype != 'win') {
			hideMenu(menuid, mtype);
			return;
		}
		if(mtype == 'menu') {
			hideMenu(layer, mtype);
		}
		if(ctrlObj) {
			if(!ctrlObj.getAttribute('initialized')) {
				ctrlObj.setAttribute('initialized', true);
				ctrlObj.unselectable = true;

				ctrlObj.outfunc = typeof ctrlObj.onmouseout == 'function' ? ctrlObj.onmouseout : null;
				ctrlObj.onmouseout = function() {
					if(this.outfunc) this.outfunc();
					if(duration < 3 && !JSMENU['timer'][menuid]) {
						JSMENU['timer'][menuid] = setTimeout(function () {
							hideMenu(menuid, mtype);
						}, timeout);
					}
				};

				ctrlObj.overfunc = typeof ctrlObj.onmouseover == 'function' ? ctrlObj.onmouseover : null;
				ctrlObj.onmouseover = function(e) {
					doane(e);
					if(this.overfunc) this.overfunc();
					if(evt == 'click') {
						clearTimeout(JSMENU['timer'][menuid]);
						JSMENU['timer'][menuid] = null;
					} else {
						for(var i in JSMENU['timer']) {
							if(JSMENU['timer'][i]) {
								clearTimeout(JSMENU['timer'][i]);
								JSMENU['timer'][i] = null;
							}
						}
					}
				};
			}
		}

		if(!menuObj.getAttribute('initialized')) {
			menuObj.setAttribute('initialized', true);
			menuObj.ctrlkey = ctrlid;
			menuObj.mtype = mtype;
			menuObj.layer = layer;
			menuObj.cover = cover;
			if(ctrlObj && ctrlObj.getAttribute('fwin')) {menuObj.scrolly = true;}
			menuObj.style.position = 'absolute';
			menuObj.style.zIndex = zindex + layer;
			menuObj.onclick = function(e) {
				return doane(e, 0, 1);
			};
			if(duration < 3) {
				if(duration > 1) {
					menuObj.onmouseover = function() {
						clearTimeout(JSMENU['timer'][menuid]);
						JSMENU['timer'][menuid] = null;
					};
				}
				if(duration != 1) {
					menuObj.onmouseout = function() {
						JSMENU['timer'][menuid] = setTimeout(function () {
							hideMenu(menuid, mtype);
						}, timeout);
					};
				}
			}
			if(cover) {
				var coverObj = document.createElement('div');
				coverObj.id = menuid + '_cover';
				coverObj.style.position = 'absolute';
				coverObj.style.zIndex = menuObj.style.zIndex - 1;
				coverObj.style.left = coverObj.style.top = '0px';
				coverObj.style.width = '100%';
				coverObj.style.height = Math.max(document.documentElement.clientHeight, document.body.offsetHeight) + 'px';
				coverObj.style.backgroundColor = '#000';
				coverObj.style.filter = 'progid:DXImageTransform.Microsoft.Alpha(opacity=50)';
				coverObj.style.opacity = 0.5;
				coverObj.onclick = function () { hideMenu(); };
				PZEM('append_parent').appendChild(coverObj);
				_attachEvent(window, 'load', function () {
					coverObj.style.height = Math.max(document.documentElement.clientHeight, document.body.offsetHeight) + 'px';
				}, document);
			}
		}
		if(drag) {
			dragobj.style.cursor = 'move';
			dragobj.onmousedown = function(event) {try{dragMenu(menuObj, event, 1);}catch(e){}};
		}
		if(cover) PZEM(menuid + '_cover').style.display = '';
		if(fade) {
			var O = 0;
			var fadeIn = function(O) {
				if(O > 100) {
					clearTimeout(fadeInTimer);
					return;
				}
				menuObj.style.filter = 'progid:DXImageTransform.Microsoft.Alpha(opacity=' + O + ')';
				menuObj.style.opacity = O / 100;
				O += 20;
				var fadeInTimer = setTimeout(function () {
					fadeIn(O);
				}, 40);
			};
			fadeIn(O);
			menuObj.fade = true;
		} else {
			menuObj.fade = false;
		}
		menuObj.style.display = '';
		if(ctrlObj && ctrlclass) {
			ctrlObj.className += ' ' + ctrlclass;
			menuObj.setAttribute('ctrlid', ctrlid);
			menuObj.setAttribute('ctrlclass', ctrlclass);
		}
		if(pos != '*') {
			setMenuPosition(showid, menuid, pos);
		}
		if(BROWSER.ie && BROWSER.ie < 7 && winhandlekey && PZEM('fwin_' + winhandlekey)) {
			PZEM(menuid).style.left = (parseInt(PZEM(menuid).style.left) - parseInt(PZEM('fwin_' + winhandlekey).style.left)) + 'px';
			PZEM(menuid).style.top = (parseInt(PZEM(menuid).style.top) - parseInt(PZEM('fwin_' + winhandlekey).style.top)) + 'px';
		}
		if(maxh && menuObj.scrollHeight > maxh) {
			menuObj.style.height = maxh + 'px';
			if(BROWSER.opera) {
				menuObj.style.overflow = 'auto';
			} else {
				menuObj.style.overflowY = 'auto';
			}
		}

		if(!duration) {
			setTimeout('hideMenu(\'' + menuid + '\', \'' + mtype + '\')', timeout);
		}

		if(!in_array(menuid, JSMENU['active'][layer])) JSMENU['active'][layer].push(menuid);
		menuObj.cache = cache;
		if(layer > JSMENU['layer']) {
			JSMENU['layer'] = layer;
		}
	}
	var dragMenuDisabled = false;
	function dragMenu(menuObj, e, op) {
		e = e ? e : window.event;
		if(op == 1) {
			if(dragMenuDisabled || in_array(e.target ? e.target.tagName : e.srcElement.tagName, ['TEXTAREA', 'INPUT', 'BUTTON', 'SELECT'])) {
				return;
			}
			JSMENU['drag'] = [e.clientX, e.clientY];
			JSMENU['drag'][2] = parseInt(menuObj.style.left);
			JSMENU['drag'][3] = parseInt(menuObj.style.top);
			document.onmousemove = function(e) {try{dragMenu(menuObj, e, 2);}catch(err){}};
			document.onmouseup = function(e) {try{dragMenu(menuObj, e, 3);}catch(err){}};
			doane(e);
		}else if(op == 2 && JSMENU['drag'][0]) {
			var menudragnow = [e.clientX, e.clientY];
			menuObj.style.left = (JSMENU['drag'][2] + menudragnow[0] - JSMENU['drag'][0]) + 'px';
			menuObj.style.top = (JSMENU['drag'][3] + menudragnow[1] - JSMENU['drag'][1]) + 'px';
			menuObj.removeAttribute('top_');menuObj.removeAttribute('left_');
			doane(e);
		}else if(op == 3) {
			JSMENU['drag'] = [];
			document.onmousemove = null;
			document.onmouseup = null;
		}
	}
	function setMenuPosition(showid, menuid, pos) {
		var showObj = PZEM(showid);
		var menuObj = menuid ? PZEM(menuid) : PZEM(showid + '_menu');
		if(isUndefined(pos) || !pos) pos = '43';
		var basePoint = parseInt(pos.substr(0, 1));
		var direction = parseInt(pos.substr(1, 1));
		var important = pos.indexOf('!') != -1 ? 1 : 0;
		var sxy = 0, sx = 0, sy = 0, sw = 0, sh = 0, ml = 0, mt = 0, mw = 0, mcw = 0, mh = 0, mch = 0, bpl = 0, bpt = 0;

		if(!menuObj || (basePoint > 0 && !showObj)) return;
		if(showObj) {
			sxy = fetchOffset(showObj);
			sx = sxy['left'];
			sy = sxy['top'];
			sw = showObj.offsetWidth;
			sh = showObj.offsetHeight;
		}
		mw = menuObj.offsetWidth;
		mcw = menuObj.clientWidth;
		mh = menuObj.offsetHeight;
		mch = menuObj.clientHeight;

		switch(basePoint) {
			case 1:
				bpl = sx;
				bpt = sy;
				break;
			case 2:
				bpl = sx + sw;
				bpt = sy;
				break;
			case 3:
				bpl = sx + sw;
				bpt = sy + sh;
				break;
			case 4:
				bpl = sx;
				bpt = sy + sh;
				break;
		}
		switch(direction) {
			case 0:
				menuObj.style.left = (document.body.clientWidth - menuObj.clientWidth) / 2 + 'px';
				mt = (document.documentElement.clientHeight - menuObj.clientHeight) / 2;
				break;
			case 1:
				ml = bpl - mw;
				mt = bpt - mh;
				break;
			case 2:
				ml = bpl;
				mt = bpt - mh;
				break;
			case 3:
				ml = bpl;
				mt = bpt;
				break;
			case 4:
				ml = bpl - mw;
				mt = bpt;
				break;
		}
		var scrollTop = Math.max(document.documentElement.scrollTop, document.body.scrollTop);
		var scrollLeft = Math.max(document.documentElement.scrollLeft, document.body.scrollLeft);
		if(!important) {
			if(in_array(direction, [1, 4]) && ml < 0) {
				ml = bpl;
				if(in_array(basePoint, [1, 4])) ml += sw;
			} else if(ml + mw > scrollLeft + document.body.clientWidth && sx >= mw) {
				ml = bpl - mw;
				if(in_array(basePoint, [2, 3])) {
					ml -= sw;
				} else if(basePoint == 4) {
					ml += sw;
				}
			}
			if(in_array(direction, [1, 2]) && mt < 0) {
				mt = bpt;
				if(in_array(basePoint, [1, 2])) mt += sh;
			} else if(mt + mh > scrollTop + document.documentElement.clientHeight && sy >= mh) {
				mt = bpt - mh;
				if(in_array(basePoint, [3, 4])) mt -= sh;
			}
		}
		if(pos.substr(0, 3) == '210') {
			ml += 69 - sw / 2;
			mt -= 5;
			if(showObj.tagName == 'TEXTAREA') {
				ml -= sw / 2;
				mt += sh / 2;
			}
		}
		if(direction == 0 || menuObj.scrolly) {
			if(BROWSER.ie && BROWSER.ie < 7) {
				if(direction == 0) mt += scrollTop;
			} else {
				if(menuObj.scrolly) mt -= scrollTop;
				menuObj.style.position = 'fixed';
			}
		}
		if(ml) menuObj.style.left = ml + 'px';
		if(mt) menuObj.style.top = mt + 'px';
		if(direction == 0 && BROWSER.ie && !document.documentElement.clientHeight) {
			menuObj.style.position = 'absolute';
			menuObj.style.top = (document.body.clientHeight - menuObj.clientHeight) / 2 + 'px';
		}
		if(menuObj.style.clip && !BROWSER.opera) {
			menuObj.style.clip = 'rect(auto, auto, auto, auto)';
		}
	}
	function hideMenu(attr, mtype) {
		attr = isUndefined(attr) ? '' : attr;
		mtype = isUndefined(mtype) ? 'menu' : mtype;
		if(attr == '') {
			for(var i = 1; i <= JSMENU['layer']; i++) {
				hideMenu(i, mtype);
			}
			return;
		} else if(typeof attr == 'number') {
			for(var j in JSMENU['active'][attr]) {
				hideMenu(JSMENU['active'][attr][j], mtype);
			}
			return;
		}else if(typeof attr == 'string') {
			var menuObj = PZEM(attr);

			if(!menuObj) {
				return;
			}
			var ctrlObj = '', ctrlclass = '';
			if((ctrlObj = PZEM(menuObj.getAttribute('ctrlid'))) && (ctrlclass = menuObj.getAttribute('ctrlclass'))) {
				var reg = new RegExp(' ' + ctrlclass);
				ctrlObj.className = ctrlObj.className.replace(reg, '');
			}
			clearTimeout(JSMENU['timer'][attr]);
			var hide = function() {
				if(menuObj.cache) {
					if(menuObj.style.visibility != 'hidden') {
						menuObj.style.display = 'none';
						if(menuObj.cover) PZEM(attr + '_cover').style.display = 'none';
					}
				}else {
					menuObj.parentNode.removeChild(menuObj);
					if(menuObj.cover) PZEM(attr + '_cover').parentNode.removeChild(PZEM(attr + '_cover'));
				}
				var tmp = [];
				for(var k in JSMENU['active'][menuObj.layer]) {
					if(attr != JSMENU['active'][menuObj.layer][k]) tmp.push(JSMENU['active'][menuObj.layer][k]);
				}
				JSMENU['active'][menuObj.layer] = tmp;
			};
			if(menuObj.fade) {
				var O = 100;
				var fadeOut = function(O) {
					if(O == 0) {
						clearTimeout(fadeOutTimer);
						hide();
						return;
					}
					menuObj.style.filter = 'progid:DXImageTransform.Microsoft.Alpha(opacity=' + O + ')';
					menuObj.style.opacity = O / 100;
					O -= 20;
					var fadeOutTimer = setTimeout(function () {
						fadeOut(O);
					}, 40);
				};
				fadeOut(O);
			} else {
				hide();
			}
		}
	}
	
	function fetchOffset(obj, mode) {
		var left_offset = 0, top_offset = 0, mode = !mode ? 0 : mode;

		if(obj.getBoundingClientRect && !mode) {
			var rect = obj.getBoundingClientRect();
			var scrollTop = Math.max(document.documentElement.scrollTop, document.body.scrollTop);
			var scrollLeft = Math.max(document.documentElement.scrollLeft, document.body.scrollLeft);
			if(document.documentElement.dir == 'rtl') {
				scrollLeft = scrollLeft + document.documentElement.clientWidth - document.documentElement.scrollWidth;
			}
			left_offset = rect.left + scrollLeft - document.documentElement.clientLeft;
			top_offset = rect.top + scrollTop - document.documentElement.clientTop;
		}
		if(left_offset <= 0 || top_offset <= 0) {
			left_offset = obj.offsetLeft;
			top_offset = obj.offsetTop;
			while((obj = obj.offsetParent) != null) {
				position = getCurrentStyle(obj, 'position', 'position');
				if(position == 'relative') {
					continue;
				}
				left_offset += obj.offsetLeft;
				top_offset += obj.offsetTop;
			}
		}
		return {'left' : left_offset, 'top' : top_offset};
	}